﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace MyTime.Controls
{
    /// <summary>
    /// Interaction logic for AdvTextBox.xaml
    /// </summary>
    public partial class AdvTextBox : UserControl
    {
        private Label grayhint;
        private VisualBrush hintbrush;

        private double actHeigth;
        private double initialcntrlWidth;

        public int AutoCompleteThreshold { get; set; }

        public event EventHandler<EventArgs> DefaultAction = delegate { };

        public event EventHandler<EventArgs> EscapeAction = delegate { };

        private string labelString;

        public string LabelString
        {
            get { return labelString; }
            set
            {
                labelString = value;
                grayhint.Content = value;
                OnPropertyChanged("LabelString");
            }
        }

        private string text;

        public string Text
        {
            get { return text; }
            set
            {
                text = value;
                OnPropertyChanged("Text");
                txtTextBox.Text = value;
                if (string.IsNullOrEmpty(txtTextBox.Text))
                    txtTextBox.Background = hintbrush;
            }
        }

        private List<string> autoCompleteList;

        public List<string> AutoCompleteList
        {
            get { return autoCompleteList; }
            set { autoCompleteList = value; }
        }

        private int txtheight;

        public int TxtHeight
        {
            get { return txtheight; }
            set
            {
                txtheight = value;
                txtTextBox.Height = txtheight;
                this.Height = txtheight;
                actHeigth = txtheight;
            }
        }
        
        public double Width
        {
            set
            {                
                txtTextBox.Width = value;
            }
        }

        public AdvTextBox()
        {
            grayhint = new Label();
            grayhint.Foreground = new SolidColorBrush(Colors.Gray);
            grayhint.Content = LabelString;
            hintbrush = new VisualBrush(grayhint);
            hintbrush.Stretch = Stretch.None;
            hintbrush.AlignmentX = AlignmentX.Left;
            AutoCompleteThreshold = 3;

            InitializeComponent();

            LabelString = "LabelString";

            txtTextBox.GotFocus += new RoutedEventHandler(txtTextBox_GotFocus);
            txtTextBox.LostFocus += new RoutedEventHandler(txtTextBox_LostFocus);
            txtTextBox.TextChanged += new TextChangedEventHandler(txtTextBox_TextChanged);
            this.IsVisibleChanged += new DependencyPropertyChangedEventHandler(AdvTextBox_IsVisibleChanged);

            listBox1.KeyDown += new KeyEventHandler(listBox1_KeyDown);
            listBox1.MouseDoubleClick += new MouseButtonEventHandler(listBox1_MouseDoubleClick);
            listBox1.Visibility = System.Windows.Visibility.Hidden;

            txtTextBox.Background = hintbrush;
            autoCompleteList = new List<string>();
            actHeigth = this.ActualHeight;
            initialcntrlWidth = this.ActualWidth;
        }

        void AdvTextBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            ResetLayout();
        }

        private void ResetLayout()
        {
            listBox1.Visibility = System.Windows.Visibility.Hidden;
            this.Height = actHeigth;
            this.Width = initialcntrlWidth;            
        }

        void listBox1_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (listBox1.SelectedValue != null)
            {
                txtTextBox.Text = listBox1.SelectedValue.ToString();
                txtTextBox.Focus();
                txtTextBox.CaretIndex = txtTextBox.Text.Length;

                listBox1.Visibility = System.Windows.Visibility.Hidden;
                this.Height = actHeigth;
            }
        }

        void listBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                txtTextBox.Text = listBox1.SelectedValue.ToString();
                txtTextBox.Focus();
                txtTextBox.CaretIndex = txtTextBox.Text.Length;

                ResetLayout();
            }
        }

        void txtTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(txtTextBox.Text))
                txtTextBox.Background = hintbrush;

            Text = txtTextBox.Text;
            //ResetLayout();
        }

        void txtTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (txtTextBox.ActualWidth > initialcntrlWidth)
                this.Width = txtTextBox.ActualWidth;

            if (string.IsNullOrEmpty(txtTextBox.Text))
                txtTextBox.Background = hintbrush;
            else
                txtTextBox.Background = new SolidColorBrush(Colors.White);

            if (txtTextBox.Text.Length >= AutoCompleteThreshold && AutoCompleteList != null && 
                txtTextBox.IsFocused)
            {
                //Check the auto complete list for similar text.
                var sel = AutoCompleteList.Where(p => p != null && p.ToString().ToUpper().Contains(txtTextBox.Text.ToUpper()));
                if (sel.Count() > 0)
                {
                    listBox1.Visibility = System.Windows.Visibility.Visible;
                    listBox1.ItemsSource = sel.Distinct();
                    this.Height = actHeigth + 150;
                    return;
                }
            }

            listBox1.Visibility = System.Windows.Visibility.Hidden;
            this.Height = actHeigth;
        }

        void txtTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            txtTextBox.Background = new SolidColorBrush(Colors.White);
        }

        private void txtTextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                ResetLayout();
                EscapeAction(this, EventArgs.Empty);
                return;
            }

            if (e.Key != Key.Enter)
            {
                ResetLayout();
                return;
            }
            else
            {
                Text = txtTextBox.Text;
                ResetLayout();
                DefaultAction(this, EventArgs.Empty);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private void txtTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Down && listBox1.Visibility == System.Windows.Visibility.Visible)
            {
                listBox1.Focus();
                listBox1.SelectedIndex = 0;
            }
        }
    }
}
